/*
 * PUtility.h
 *
 *  Created on: Oct 11, 2014
 *      Author: yuliang
 */

#ifndef PUTILITY_H_
#define PUTILITY_H_

#include <time.h>
#include <vector>
#include <queue>
#include <string>

/*
 * @brief       一天的秒数
 */
#define SECONDS_DATE                   86400

class CPUtility {
	#define DateFormatLength				20
public:
	enum PUtilityDateFlag {
		PUDToday = 0,
		PUDYesterday,
	};

	enum DateInfoFlag {
		YearFlag,
		MonthFlag,
		DayFlag,
		HourFlag,
		MinuteFlag,
		SecondFlag,

		DateInfoFlagCount,
	};
	typedef std::vector<unsigned short> VecDateInfo_t;
public:
	CPUtility();
	virtual ~CPUtility();
	static inline void Random_seed(int seed) { if(!seed) m_PUtilitySeed = (unsigned)time(0); else m_PUtilitySeed = seed; }
	static inline int Random_int(int min, int max) { m_PUtilitySeed = 214013 * m_PUtilitySeed + 2531011; return min + (m_PUtilitySeed ^ m_PUtilitySeed>>15) % (max - min + 1); }
	static inline float Random_float(float min, float max) { m_PUtilitySeed = 214013 * m_PUtilitySeed + 2531011; return min + (m_PUtilitySeed >> 16) * (1.0f / 65535.0f) * (max - min); }

	template<typename T>
	static inline bool With1Byte(const T& b) { if (0 == b || 0 != (b & (b - 1))) return false; return true; }
	template<typename T>
	static inline bool WithThisByte(const T& s, const T& b) { if (!With1Byte<T>(b)) return false; return s & b; }
	template<typename T>
	static inline bool Set1Byte(T& s, const T& b) { if (!With1Byte<T>(b)) return false; s |= b; return true; }
	template<typename T>
	static inline bool Rm1Byte(T& s, const T& b) { if (!With1Byte<T>(b)) return false; s &= ~b; return true; }

	static bool GetStringDate(std::string& date, PUtilityDateFlag flag);
	static bool GetStringTime(std::string& time, int diffTime = 0);
	static void GetCurrentDate(VecDateInfo_t& info);
private:
	static unsigned int m_PUtilitySeed;
	static char m_PUtilityDate[DateFormatLength];
};

/*
 * queue obj_ptr
 * new/get/set
 */
#define QUEUE_OBJ_PTR_FUNC(ClassName, ObjName) \
private: \
	typedef std::queue<ClassName*>		TQue##ObjName; \
	TQue##ObjName						m_Que##ObjName; \
	inline ClassName* create##ObjName() { return new ClassName; } \
	\
public: \
	inline ClassName* get##ObjName() { \
		if (m_Que##ObjName.empty()) \
			return create##ObjName(); \
		ClassName* __t__ = m_Que##ObjName.front(); \
		m_Que##ObjName.pop(); \
		return __t__; \
	} \
	inline void set##ObjName(ClassName *__t__) { if (nullptr != __t__) m_Que##ObjName.push(__t__); }

#include <assert.h>
#define CONFIG_MAP_FUNC_SET_GET_INIT(mapT, keyT, valuePtrT) \
private: \
	typedef mapT<keyT, valuePtrT*> Map##keyT##valuePtrT##_t; \
	Map##keyT##valuePtrT##_t m_Map##keyT##valuePtrT; \
public: \
	inline const valuePtrT* Get##valuePtrT(const keyT& __k) const { \
		Map##keyT##valuePtrT##_t::const_iterator __it = m_Map##keyT##valuePtrT.find(__k); \
		if (__it != m_Map##keyT##valuePtrT.end()) \
			return __it->second; \
		return nullptr; \
	} \
	inline void Set##valuePtrT(const keyT& __k, valuePtrT* __v) { \
		assert(m_Map##keyT##valuePtrT.find(__k) == m_Map##keyT##valuePtrT.end()); \
		m_Map##keyT##valuePtrT[__k] = __v; \
	}

#define CONFIG_MAP_FUNC_UNCONST_SET_GET_INIT(mapT, keyT, valuePtrT) \
private: \
	typedef mapT<keyT, valuePtrT*> Map##keyT##valuePtrT##_t; \
	Map##keyT##valuePtrT##_t m_Map##keyT##valuePtrT; \
public: \
	inline valuePtrT* Get##valuePtrT(const keyT& __k) const { \
		Map##keyT##valuePtrT##_t::const_iterator __it = m_Map##keyT##valuePtrT.find(__k); \
		if (__it != m_Map##keyT##valuePtrT.end()) \
			return __it->second; \
		return nullptr; \
	} \
	inline void Set##valuePtrT(const keyT& __k, valuePtrT* __v) { \
		assert(m_Map##keyT##valuePtrT.find(__k) == m_Map##keyT##valuePtrT.end()); \
		m_Map##keyT##valuePtrT[__k] = __v; \
	}

#endif /* PUTILITY_H_ */
